package com.heatingcharge.security.util;
import com.heatingcharge.security.JwtUser;
import io.jsonwebtoken.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Component;
import org.thymeleaf.standard.expression.FragmentSignatureUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.sql.ClientInfoStatus;
import java.util.*;

/**
 * Created with IntelliJ IDEA.
 * Description: heating_charge_server
 * User: Devin
 * Date: 2019-07-03
 * Time: 16:49
 */
@Log4j2
@Component
public class JwtUtil {
    //用户名
    private static final String USERNAME = Claims.SUBJECT;
    //userId
    private static final String USERID = "userid";
    //创建时间
    private static final String CREATED = "created";
    //权限列表
    private static final String AUTHORITIES = "authorities";
    //密钥
    private static final String SECRET = "abcdefgh";
    // 过期时间1小时
    private static final long EXPIRE_TIME =60*60*1000;

    @Value("${jwt.header}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String authTokenStart;

    /**
     * 生成Token
     * @param jwtUser
     * @return
     */
    public static String generateToken(JwtUser jwtUser){
        Map<String,Object> claims=new HashMap<>(3);
        claims.put(USERID,jwtUser.getUserId());
        claims.put(USERNAME, jwtUser.getUsername());
        claims.put(CREATED, new Date());
        claims.put(AUTHORITIES, jwtUser.getAuthorities());
        return generateToken(claims);
    }

    private static String generateToken(Map<String, Object> claims) {
        Date expirationDate=new Date(System.currentTimeMillis()+EXPIRE_TIME);
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(expirationDate)
                .signWith(SignatureAlgorithm.HS512,SECRET)
                .compact();
    }



    /**
     * 根据请求token获取登录信息
     * @param request
     * @return
     */
    public JwtUser getJwtUserFromToken(HttpServletRequest request){
        //获取请求携带的Token
        String token=getToken(request);
        if (StringUtils.isNotEmpty(token)){
            Claims claims=getClaimsFromToken(token);
            if (claims==null){
                return null;
            }
            String username=claims.getSubject();
            if (isTokenExpired(token)){
                return null;
            }
            //解析对应的权限及用户信息
            Object authors=claims.get(AUTHORITIES);
            Integer userId=(Integer)claims.get(USERID);
            Set<String> perms=new HashSet<>();
            if (authors instanceof List){
                for (Object object : (List) authors) {
                    perms.add(((Map) object).get("authority").toString());
                }
            }
            Collection<? extends GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(perms.toArray(new String[0]));
//            List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(perms.toArray(new String[0]));
            return new JwtUser(userId,username,"",authorities);
        }
        return null;
    }

    /**
     * 从token中获取用户名
     * @param token
     * @return
     */
    public static String getUserNameFromToken(String token){
        Claims claims=getClaimsFromToken(token);
        return claims.getSubject();
    }

    /**
     * 获取token
     * @param request
     * @return
     */
    private String getToken(HttpServletRequest request){
//        Enumeration<String> headers = request.getHeaders(tokenHeader);
//        Enumeration<String> headerNames = request.getHeaderNames();
//        String accept=request.getHeader("Accept");
        String token=request.getHeader(tokenHeader);
        if(StringUtils.isNotEmpty(token)){
            token=token.substring(authTokenStart.length());
        }
        return token;
    }

    /**
     * 获取Claims
     * @param token
     * @return
     */
    private static Claims getClaimsFromToken(String token){
        Claims claims;
        try {
            claims=Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch (Exception e) {
            claims=null;
        }
        return claims;
    }

    /**
     * 判断token是否过期
     * @param token
     * @return
     */
    private static Boolean isTokenExpired(String token){
        try {
            Claims claims=getClaimsFromToken(token);
            Date expiration=claims.getExpiration();
            return expiration.before(new Date());
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 验证token
     * @param token
     * @param username
     * @return
     */
    private static Boolean validateToken(String token,String username){
        String userName=getUserNameFromToken(token);
        return (userName.equals(username) && !isTokenExpired(token));
    }
}
